package com.examiner.filter;

import com.alibaba.fastjson.JSON;
import com.examiner.config.TokenFilterUrlConfigProperties;
import com.examiner.result.EmptyObject;
import com.examiner.result.Result;
import com.examiner.token.JwtUtil;
import io.jsonwebtoken.Claims;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.util.Set;

@Component
public class TokenFilter implements GlobalFilter, Ordered {

    @Resource
    TokenFilterUrlConfigProperties tokenFilterUrls;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("token");
        // 1. 获取请求url
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
       // System.out.println(request.getMethod().toString());
        // 2. 过滤不拦截的URL，直接放行,用chain.filter(exchange) 放行登录 /manager/login
        String value = request.getPath().value();  // /manager/login
        // 获取请求方式
        //System.out.println(request.getMethod().matches("GET"));
        Set<String> urls = tokenFilterUrls.getUrls();
        System.out.println(urls);
        System.out.println(value);
        if (urls.contains(value)){
            System.out.println("get放行");
            return chain.filter(exchange);
        }
        // 3. 从 header 中 获取 token
        String token = request.getHeaders().getFirst("token");
        System.out.println(token);
        // 4. token 不存在，直接封装响应体
        if (token == null){ return getVoidMono(response); }
        // 5. 解析 token ,发生问题 封装响应体
        Claims claims = null;
        try{
            claims = JwtUtil.parseJWT(token);
        }catch (Exception e){
            return getVoidMono(response);
        }
        System.out.println(claims);
        // 6. 以上校验成功 成功, 放行
        // 其他操作   校验用户身份等(根据业务权限进行判断)
        return chain.filter(exchange);
    }

    // 封装响应
    private Mono<Void> getVoidMono(ServerHttpResponse serverHttpResponse) {
        serverHttpResponse.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        Result<EmptyObject> entity = new Result<>(50001, "认证失败", false, EmptyObject.empty);
        DataBuffer dataBuffer = serverHttpResponse.bufferFactory().wrap(JSON.toJSONString(entity).getBytes());
        return serverHttpResponse.writeWith(Flux.just(dataBuffer));
    }


    @Override
    public int getOrder() {
        return 0;
    }
}
